package com.koron.bean.base;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.koron.bean.util.ServletUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.http.HttpStatus;

import java.io.Serializable;

/**
 * @author zhouj
 * @date 2021/8/11 15:00
 **/
@NoArgsConstructor
@Data
@ApiModel("响应类实体对象")
public class Response<T> implements Serializable {

    private static final long serialVersionUID = -2597067768212381245L;

    @ApiModelProperty(value = "状态码", position = 1)
    private int code;

    @ApiModelProperty(value = "说明", position = 2)
    private String description;

    @ApiModelProperty(value = "返回数据", position = 4)
    private T data;

    @ApiModelProperty(value = "总条数", position = 5)
    private Long total;

    public static <T> Response<T> base(HttpStatus status, String message, T data) {

        return base(status, message, data, null);
    }

    public static <T> Response<T> base(HttpStatus status, String message, T data, Long total) {
        Response<T> response = new Response<T>();
        response.setCode(status.value());
        response.setData(data);
        response.setDescription(message);
        response.setTotal(total);
        return response;
    }

    public static <T> Response<T> base(int code, String message, T data) {
        Response<T> response = new Response<T>();
        response.setCode(code);
        response.setData(data);
        response.setDescription(message);
        return response;
    }

    public static <T> Response<T> ok() {
        return success(null);
    }

    public static <T> Response<T> ok(T data) {
//        return ok("执行成功", data);
        return ok(StrUtil.join("###","执行成功","執行成功","Execution successful"), data);
    }

    public static <T> Response<T> ok(String message, T data) {
        return base(HttpStatus.OK, message, data);
    }

    public static <T> Response<T> succ(T data) {
        return success(StrUtil.join("###","执行成功","執行成功","Execution successful"), data);
    }

    public static <T> Response<T> success() {
        return success(null);
    }

    public static <T> Response<T> success(T data) {
        return success(HttpStatus.OK, data);
    }

    public static <T> Response<T> success(String message, T data) {
        return base(HttpStatus.OK, message, data);
    }

    public static <T> Response<T> success(String message, T data, Long total) {
        return base(HttpStatus.OK, message, data, total);
    }

    public static <T> Response<T> success(String message, T data, int total) {
        return base(HttpStatus.OK, message, data, (long) total);
    }

    public static <T> Response<T> succ(T data, Long total) {
        return base(HttpStatus.OK, ServletUtils.getMethodName() + "成功", data, total);
    }

    public static <T> Response<T> success(T data, Long total) {
        return base(HttpStatus.OK, ServletUtils.getMethodName() + "成功", data, total);
    }

    public static <T> Response<T> success(HttpStatus status, T data) {
        return base(status, ServletUtils.getMethodName() + "成功", data);
    }

    public static <T> Response<T> fail() {
        return fail(ServletUtils.getMethodName() + "失败");
    }

    public static <T> Response<T> fail(String message) {
        return fail(HttpStatus.INTERNAL_SERVER_ERROR, message);
    }

    public static <T> Response<T> fail(HttpStatus status, String message) {
        return base(status, message, null);
    }

    public static <T> Response<T> fail(int code, String message) {
        return base(code, message, null);
    }

    public static Response<String> flag(boolean b) {
        if (b) {
            return success();
        } else {
            return fail();
        }
    }

    @SneakyThrows
    public String toJson() {
        ObjectMapper objectMapper = SpringUtil.getBean(ObjectMapper.class);
        return objectMapper.writeValueAsString(this);
    }
}
